//
//  AnalysisHandle.m
//  hospitalUser
//
//  Created by 888 on 2021/10/9.
//

#import "AnalysisHandle.h"
#import "Safety.h"
#import "HttpRequestManager.h"
//默认文件名
static NSString *const  AnalyticsFileName = @"AppMonitor.plist";
//默认文件夹名
static NSString *const  DirectoryFileName = @"Analytics";
//队列唯一标识
static NSString *const SensorsAnalyticsSerialQueueLabel = @"cn.sensorsdata.fileStoreSerialQueue";

@interface AnalysisHandle()

@property(nonatomic,strong)NSMutableArray *events;
@property(nonatomic,strong)dispatch_queue_t queue;//串行队列（同步串行）
@property(nonatomic,assign)NSInteger maxLocalEventCount;//内存缓存事件条数

@end


@implementation AnalysisHandle


- (id)copyWithZone:(NSZone *)zone {
    return [[AnalysisHandle allocWithZone:zone] init];
}

+ (id)allocWithZone:(NSZone *)zone{
    return [self instanceHandle];
}

+ (instancetype)instanceHandle{
  static dispatch_once_t onceToken;
  static AnalysisHandle *handle = nil;
  dispatch_once(&onceToken, ^{
    handle = [[super allocWithZone:NULL] init];
  });
  return handle;
}


-(instancetype)init{
    self = [super init];
    if (self) {
        NSString *label = [NSString stringWithFormat:@"%@.%p",SensorsAnalyticsSerialQueueLabel,self];
        //创建一个串行队列
        _queue = dispatch_queue_create([label UTF8String], DISPATCH_QUEUE_SERIAL);
        //初始化内存最大缓存事件条数
        _maxLocalEventCount = 10;
    }
    return self;
}


-(NSMutableArray*)events{
  if (!_events) {
    _events = [[NSMutableArray alloc] init];
  }
  return _events;
}

- (void)setTraceId:(NSString *)traceId{
  if (!_traceId) {
    _traceId = traceId;
  }
}

- (void)setUserId:(NSString*)userId{
   _userId = userId;
}

- (void)setStaffId:(NSString *)staffId{
   _staffId = staffId;
}

- (void)setDevelopmentUrl:(NSString *)developmentUrl{
  _developmentUrl = developmentUrl;
}



// 外界调用的数据传递入口（App埋点统计）
- (void)event:(NSString *)eventId content:(NSString *)content{
  // 线程锁,防止多处调用产生并发问题
  __weak AnalysisHandle *weakSelf = self;
     @synchronized (weakSelf) {
         if (eventId) {
           NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
           if (content&&![content isEqual:@""] ) {
                [dict SafetySetObject:content forKey:@"content"];
            }
            [dict SafetySetObject:[weakSelf getCurrentTimeBySecond] forKey:@"createTime"];
            [dict SafetySetObject:eventId  forKey:@"eventId"];
            [weakSelf joinEvent:dict];
         }
     }
  
}


// 将App埋点数据写入到内存中。同步写入缓存到文件信息中
- (void)joinEvent:(NSDictionary *)dictionary{
  
    if (dictionary) {
      __weak typeof(self) weakSelf = self;
      //将存储事件的操作用队列包装起来
      dispatch_async(weakSelf.queue, ^{
          //如果当前事件条数超过当前的最大值，调用网络上传,删除内存中数据
          if (weakSelf.events.count >= weakSelf.maxLocalEventCount) {
              [weakSelf uploadFile];
          }
          //在数组中先添加事件
          [weakSelf.events addObject:dictionary];
           DEBUG_NSLog(@"在数组中添加将App埋点数据===%@",weakSelf.events)
          //将事件数据保存到缓存文件中
           [weakSelf writeEventToFile];
      });
    }
}


// 将内存中的数据写入到文件中，持久化存储
-(void)writeEventToFile{
  __weak typeof(self) weakSelf = self;
  NSArray *tmp = nil;
  @synchronized (self) {
      tmp = [weakSelf.events copy];
  }
  if (tmp) {
    //将写入文件的操作用队列包装起来
    dispatch_async(weakSelf.queue, ^{
        
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //Json解析错误信息
        NSError *error = nil;
        //将字典数据解析成Json数据
        NSData *data = [NSJSONSerialization dataWithJSONObject:tmp options:NSJSONWritingPrettyPrinted error:&error];
        if (error) {
          DEBUG_NSLog(@"The json object`s serialization error %@",error);
            return;
        }
        //判断一个给定路径是否为文件夹
        if (![[NSFileManager defaultManager] fileExistsAtPath:[weakSelf cacheFilePath]]) {
            [[NSFileManager defaultManager] createDirectoryAtPath:[weakSelf cacheFilePath] withIntermediateDirectories:YES attributes:nil error:nil];
        }
        
        NSString *cacheFile = [[weakSelf cacheFilePath] stringByAppendingPathComponent:AnalyticsFileName];
        //将数据写入到文件里
        BOOL isSuccess = [data writeToFile:cacheFile atomically:YES];
        if (isSuccess) {
           DEBUG_NSLog(@"write success");
        } else {
           DEBUG_NSLog(@"write fail");
        }
          
      });
      
       
    });
    
  }
}


- (NSString*)getCacheFilePath{
    NSString*paths = nil;
    NSString *path = [self cacheFilePath];
    //创建一个新的NSFileManager*实例,每次调用返回一个不同的指针地址,保证线程安全
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    NSDirectoryEnumerator *enumerator;
    enumerator = [fileManager enumeratorAtPath:path];
    while((path = [enumerator nextObject]) != nil) {
        if (![path isEqualToString:@".DS_Store"]) {
            paths = [NSString stringWithFormat:@"%@%@%@",[self cacheFilePath],@"/",path];
            DEBUG_NSLog(@"读取文件路径=%@",paths);
        }
    }
    return paths;
}


- (void)deleteOldCacheFile{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager removeItemAtPath:[self getCacheFilePath] error:nil];
    DEBUG_NSLog(@"清除本地缓存%@",[self getCacheFilePath]);
}

- (void)getCacheFileDataSource{
  __weak typeof(self) weakSelf = self;
  [[AnalysisHandle instanceHandle]setTraceId:[weakSelf getCurrentTimeBySecond]];
    //将从文件中读取数据的操作用队列包装起来
    dispatch_async(weakSelf.queue, ^{
        //从文件路径中读取数据
        NSData *data = [NSData dataWithContentsOfFile:[weakSelf getCacheFilePath]];
        NSArray *allEvents;
        //这里需要判断data是否为空，不为空才可以转化
        if (data) {
            //解析在文件中读取的Json数据
            allEvents = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        }
        //将文件内的数据保存到内存中
        if (allEvents) {
           [weakSelf.events addObjectsFromArray:allEvents];
        }
        DEBUG_NSLog(@"解析在文件中读取的Json数据%@",weakSelf.events);
        if (weakSelf.events.count>0) {
            [weakSelf uploadFile];
        }
    });
  
}

// App埋点统计从前台回到后台触发一次
- (void)appDidEnterBackgroundUploadFile{
  
  if (self.events.count>0) {
      [self uploadFile];
  }
  
}


// App埋点统计数据上传服务端，成功后就删除缓存本地数据
- (void)uploadFile{
      __weak typeof(self) weakSelf = self;
     NSMutableDictionary * params = [weakSelf getRequestParams];
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      // 调用接口上传埋点数据
        [[HttpRequestManager sharedDefaultManager]requestPostWithPath:Upload_API_URL params:params completed:^(BOOL ret, id  _Nonnull obj) {
            DEBUG_NSLog(@"调用接口上传埋点数据===%@\n 请求参数=%@",obj,params);
            if (ret) {
                [weakSelf deleteOldCacheFile];
                [weakSelf.events removeAllObjects];
            }
        }];
    });
  
}


- (NSMutableDictionary*)getRequestParams{
   
    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
    [params SafetySetObject:_traceId forKey:@"traceId"];
    if (_userId) {
        [params SafetySetObject:_userId forKey:@"userId"];
    }
    if (_staffId) {
        [params SafetySetObject:_staffId forKey:@"staffId"];
    }
    [params SafetySetObject:[self.events copy] forKey:@"eventInfoList"];
    [params SafetySetObject:@"GYTJK" forKey:@"platform"];
   return params;
}

//获取当前时间戳(以毫秒为单位)
- (NSString *)getCurrentTimeBySecond {

  NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;
  [formatter setDateStyle:NSDateFormatterMediumStyle];
  [formatter setTimeStyle:NSDateFormatterShortStyle];
  [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss SSS"];
  //设置想要的格式，hh与HH的区别:分别表示12小时制,24小时制
  //设置时区,这一点对时间的处理有时很重要
  //NSTimeZone*timeZone=[NSTimeZone timeZoneWithName:@"Asia/Shanghai"];
  NSTimeZone*timeZone=[NSTimeZone systemTimeZone];
  [formatter setTimeZone:timeZone];
  NSDate *datenow = [NSDate date];
  NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]*1000];
  DEBUG_NSLog(@"获取时间戳以毫秒为单位---->>>>%@",timeSp);
  return timeSp;
}


//文件存储路径
- (NSString *)cacheFilePath{
    NSString *paths = [NSString stringWithFormat:@"%@/%@",[NSSearchPathForDirectoriesInDomains(
                  NSDocumentDirectory, NSUserDomainMask, YES)firstObject],DirectoryFileName];
    DEBUG_NSLog(@"文件存储路径=%@",paths);
    return paths;
}

@end

